package net.wicp.tams.component.components;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.tapestry5.BindingConstants;
import org.apache.tapestry5.ComponentResources;
import org.apache.tapestry5.Link;
import org.apache.tapestry5.MarkupWriter;
import org.apache.tapestry5.Renderable;
import org.apache.tapestry5.StreamResponse;
import org.apache.tapestry5.annotations.Environmental;
import org.apache.tapestry5.annotations.Events;
import org.apache.tapestry5.annotations.Import;
import org.apache.tapestry5.annotations.Parameter;
import org.apache.tapestry5.annotations.Property;
import org.apache.tapestry5.annotations.SetupRender;
import org.apache.tapestry5.internal.util.CaptureResultCallback;
import org.apache.tapestry5.ioc.Messages;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
import org.apache.tapestry5.json.JSONArray;
import org.apache.tapestry5.json.JSONObject;
import org.apache.tapestry5.services.Request;
import org.apache.tapestry5.services.javascript.JavaScriptSupport;

import net.wicp.tams.commons.Result;
import net.wicp.tams.commons.apiext.CollectionUtil;
import net.wicp.tams.commons.apiext.JSONUtil;
import net.wicp.tams.commons.apiext.ReflectAssist;
import net.wicp.tams.commons.apiext.StringUtil;
import net.wicp.tams.commons.callback.IConvertValue;
import net.wicp.tams.component.SymbolConstantsCus;
import net.wicp.tams.component.tools.TapestryAssist;

/***
 * 拖拽选择组件
 * 
 * @author andy.zhou
 *
 */
@Import(library = { "${path.jquery.plugin}/json2template.js" }, stylesheet = {
		"${path.comassets}/css/selgroup.css" }, stack = "easyuistack")
// 示例:@OnEvent(value = "save") private OperateResult sava(JSONArray selIds) {
@Events({ SymbolConstantsCus.EVENT_SAVE })
public class SelGroup {

	private static final int minWidth = 200;
	private static final int minHeight = 200;

	@Inject
	protected ComponentResources resources;

	@Inject
	protected Messages messages;// 国际化

	@Inject
	protected Request request;

	@Environmental
	protected JavaScriptSupport javaScriptSupport;
	/***
	 * 组件ID
	 */
	@Parameter(value = "prop:componentResources.id", defaultPrefix = BindingConstants.LITERAL)
	@Property
	private String id;
	/***
	 * 标题
	 */
	@Parameter(required = false, defaultPrefix = BindingConstants.LITERAL)
	@Property
	private String title;

	String defaultTitle() {
		return resources.getMessages().get("defaultTitle");
	}

	/***
	 * 左边框标题
	 */
	@Parameter(required = false, defaultPrefix = BindingConstants.LITERAL)
	@Property
	private String titleleft;

	String defaultTitleleft() {
		return resources.getMessages().get("leftTitle");
	}

	/***
	 * 右边框标题
	 */
	@Parameter(required = false, defaultPrefix = BindingConstants.LITERAL)
	@Property
	private String titleright;

	String defaultTitleright() {
		return resources.getMessages().get("rightTitle");
	}

	/****
	 * 域名
	 */
	@Parameter(defaultPrefix = BindingConstants.LITERAL)
	private String name;

	/****
	 * 需要求显的对象
	 */
	@Parameter(required = false, defaultPrefix = BindingConstants.PROP)
	private List<?> objs;

	/****
	 * 需要提取的字段名,中间用"|"分隔,可以用","分隔别称,如"a|b,b1|c"将转化为 a b1 c 三个字段<br/>
	 * 字段必须要有"id"字段,注意如果提供此字段将显示指定的字段,如果不提供此字段将取对象所有的字段
	 */
	@Parameter(required = false, defaultPrefix = BindingConstants.LITERAL)
	private List<String> cols;

	/****
	 * 字段别称集合,如果不想提供 cols 又想用到别称就可以传入此字段
	 */
	@Parameter(required = false, defaultPrefix = BindingConstants.LITERAL)
	private List<String> alias;

	/***
	 * 选择的对象 id "|"分隔
	 */
	@Parameter(required = false, defaultPrefix = BindingConstants.LITERAL)
	private List<String> select;// select 元素可能把整形传过来
	/****
	 * 需要的转换器
	 */
	@Parameter(required = false, defaultPrefix = BindingConstants.PROP)
	private Map<String, IConvertValue> convert;

	/****
	 * 组件宽度 类型：整型
	 */
	@Parameter(defaultPrefix = BindingConstants.LITERAL)
	private Integer width;

	public Integer getWidth() {
		if (resources.isBound("width") && width > minWidth) {
			return width;
		} else {
			return minWidth;
		}
	}

	/****
	 * 组件高度 类型：整型
	 */
	@Parameter(defaultPrefix = BindingConstants.LITERAL)
	private Integer height;

	/****
	 * 组件高度 类型：整型
	 */
	@Parameter(defaultPrefix = BindingConstants.LITERAL)
	private String style;

	public String getStyle() {
		StringBuffer buff = new StringBuffer("overflow:hidden;");
		if (resources.isBound("style")) {
			buff.append(style);
		}
		if (resources.isBound("height")) {
			buff.append(String.format("height:%s;", getHeight()));
		}
		if (resources.isBound("width")) {
			buff.append(String.format("width:%s;", getWidth()));
		}
		return buff.toString();
	}

	/****
	 * 执行成功后的JS动作
	 */
	@Parameter(defaultPrefix = BindingConstants.LITERAL)
	@Property
	private String sucHandle;

	/****
	 * 执行保存前检查
	 */
	@Parameter(defaultPrefix = BindingConstants.LITERAL)
	@Property
	private String checkHandle;

	/****
	 * 保存时的参数组装
	 */
	@Parameter(defaultPrefix = BindingConstants.LITERAL)
	@Property
	private String packHandle;

	public Integer getHeight() {
		if (resources.isBound("height") && height > minHeight) {
			return height;
		} else {
			return minHeight;
		}
	}

	@Property(write = false)
	private JSONArray selList;

	@Property(write = false)
	private JSONArray selUnList;
	@Property
	private JSONObject data;

	@SetupRender
	void init() {
		javaScriptSupport.require("component/rjzjh/selgroup");
		selList = new JSONArray();
		selUnList = new JSONArray();
		if (CollectionUtils.isNotEmpty(objs)) {
			List objsTrue = CollectionFactory.newList();
			Class classz = objs.get(0).getClass();
			if (ReflectAssist.isPrimitieClass(classz) || classz.getName().equals("java.lang.String")) {// 是基本数据类型
				for (Object obj : objs) {
					Map<String, String> temMap = new HashMap<String, String>();
					temMap.put("id", String.valueOf(obj));
					objsTrue.add(temMap);
				}
			} else {
				objsTrue = objs;
			}

			String[] titleary = new String[0];
			if (resources.isBound("cols") && CollectionUtils.isNotEmpty(cols)) {// 传入了cols
				titleary = cols.toArray(new String[cols.size()]);
			}
			if (resources.isBound("alias") && CollectionUtils.isNotEmpty(alias)) {// 传入了alias
				titleary = CollectionUtil.arrayMerge(String[].class, titleary, alias.toArray(new String[alias.size()]));
			}

			// 产生String
			String listStr = "[]";
			titleary = ArrayUtils.isNotEmpty(titleary) ? titleary : new String[] { "id" };
			if (resources.isBound("cols") && CollectionUtils.isNotEmpty(cols)) {// 传入了cols
				listStr = JSONUtil.getJsonForList(objsTrue, convert, titleary);
			} else {
				listStr = JSONUtil.getJsonForListAlias(objsTrue, titleary, convert);
			}
			JSONArray allList = new JSONArray(listStr);
			for (Object object : allList) {
				JSONObject ele = (JSONObject) object;
				if (CollectionUtils.isNotEmpty(select) && contains(ele.getString("id"))) {
					selList.put(ele);
				} else {
					selUnList.put(ele);
				}
			}

		}

	}

	/***
	 * 判断id是否在选择列表中,因为select 元素可能为整形
	 * 
	 * @param idstr
	 * @return
	 */
	private boolean contains(String idstr) {
		for (Object sel : select) {
			if (String.valueOf(sel).equals(idstr)) {
				return true;
			}
		}
		return false;
	}

	@Property(write = false)
	private final Renderable div = new Renderable() {
		@Override
		public void render(MarkupWriter writer) {
			String idstr = String.format("%s-%s", id, String.valueOf(data.get("id")));
			writer.element("div", "class", "drag", "id", idstr, "data-options", data);
			writer.end();
		}

	};

	/****
	 * 得到name属性
	 * 
	 * @return
	 */
	public String getName() {
		if (!resources.isBound("name")) {
			return id;
		} else {
			return this.name;
		}
	}

	/***
	 * 把已选择的id输出为select
	 * 
	 * @return
	 */
	public String getSelect() {
		if (CollectionUtils.isEmpty(select)) {
			return "[]";
		}
		JSONArray ary = new JSONArray();
		for (Object ele : select) {
			ary.put(String.valueOf(ele));
		}
		return ary.toString(true);
	}

	/***
	 * 设置可接受的元素,防止当页面出现两个组件时 接收面板 接收别人的元素
	 * 
	 * @return
	 */
	public String getAccept() {
		JSONArray allEle = new JSONArray();
		allEle.putAll(selList);
		allEle.putAll(selUnList);

		StringBuffer buff = new StringBuffer();
		if (allEle != null && allEle.length() > 0) {
			for (int i = 0; i < allEle.length(); i++) {
				JSONObject ele = allEle.getJSONObject(i);
				String idstr = String.format("%s-%s", id, ele.getString("id"));
				buff.append(String.format("#%s,", idstr));
			}
			buff.replace(buff.length() - 1, buff.length(), "");// 去除最后一个","
		}
		return buff.toString();
	}

	public Object getSaveLink() {
		Link link = resources.createEventLink("saveselectids");
		return link.toAbsoluteURI();
	}

	StreamResponse onSaveselectids() {
		String ids = request.getParameter("ids");
		JSONArray idarry = new JSONArray(ids);
		String params = request.getParameter("params");
		JSONObject paramsObj = new JSONObject(params);

		Result retobj = null;
		CaptureResultCallback<Result> callback = new CaptureResultCallback<Result>();
		resources.triggerEvent(SymbolConstantsCus.EVENT_SAVE, new Object[] { idarry, paramsObj }, callback);
		if (callback.getResult() == null) {
			retobj = Result.getError(messages.get("selgroup.errortitle"));
			return TapestryAssist.getTextStreamResponse(retobj);
		}
		retobj = callback.getResult();
		final Messages mesparent = resources.getPage().getComponentResources().getMessages();

		String key = retobj.getExcept().getErrorCode();
		if (StringUtil.isNotNull(key) && mesparent.contains(key)) {
			retobj.setMessage(mesparent.get(key));
		}
		return TapestryAssist.getTextStreamResponse(retobj);
	}

	/***
	 * 是否存在事件的的实现
	 * 
	 * @return
	 */

	public boolean getHasEvent() {
		boolean has = resources.getPage().getComponentResources().getComponentModel()
				.handlesEvent(SymbolConstantsCus.EVENT_SAVE);

		return has;
	}

}
